package com.example.document.controller;

import com.example.document.entity.ApiResponse;
import com.example.document.enumerate.ReturnEnum;
import io.minio.MinioClient;
import io.minio.PutObjectOptions;
import io.minio.Result;
import io.minio.messages.Item;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import static org.apache.commons.lang3.StringUtils.isEmpty;

@Slf4j
@RestController
@RequestMapping("/doc")
public class DocumentController {

    @Value("${cn.minio.bucketName}")
    private String bucketName;

    @Autowired
    private MinioClient minioClient;

    /**
     * 文件列表
     *
     * @param path
     * @param prefix
     * @return
     */
    @GetMapping("/list")
    public ApiResponse getFileList(@RequestParam(value = "path", required = false) String path,
                                   @RequestParam(value = "prefix", required = false) String prefix) {
        if (isEmpty(path)) {
            path = bucketName;
        }
        if (isEmpty(prefix)) {
            prefix = null;
        }
        List<String> fileList = new ArrayList();
        try {
            Iterable<Result<Item>> files = minioClient.listObjects(path, prefix);
            for (Result<Item> result : files) {
                Item item = result.get();
                log.info(item.lastModified() + ", " + item.size() + ", " + item.objectName());
                fileList.add(item.objectName());
            }
        } catch (Throwable e) {
            log.error("获取文件列表异常:{}-{}", path, prefix, e);
            return ApiResponse.error(ReturnEnum.FAIL.getMsg());
        }
        return ApiResponse.success("", fileList);
    }

    /**
     * 下载文件
     *
     * @param fileName
     * @param path
     * @param response
     * @throws IOException
     */
    @GetMapping("/download/{fileName}")
    public void download(@PathVariable("fileName") String fileName,
                         @RequestParam(value = "path", required = false) String path,
                         HttpServletResponse response) throws IOException {
        if (isEmpty(path)) {
            path = bucketName;
        }
        log.info("从{}下载{}", path, fileName);
        InputStream in = null;
        OutputStream out = null;
        try {
            in = minioClient.getObject(path, fileName);
            int len = 0;
            //5.创建数据缓冲区
            byte[] buffer = new byte[1024];
            //6.通过response对象获取OutputStream流
            out = response.getOutputStream();
            //7.将FileInputStream流写入到buffer缓冲区
            while ((len = in.read(buffer)) > 0) {
                //8.使用OutputStream将缓冲区的数据输出到客户端浏览器
                out.write(buffer, 0, len);
            }
        } catch (Throwable e) {
            log.error("下载文件{}/{}失败", path, fileName, e);
            response.getOutputStream().print("下载失败，请稍后再试！");
        } finally {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }
    }

    /**
     * 上传文件
     *
     * @param request
     * @return
     */
    @PostMapping("/upload")
    public ApiResponse upload(@RequestParam(value = "path", required = false) String path,
                              HttpServletRequest request) {
        Part file = null;
        String fileName;
        if (isEmpty(path)) {
            path = bucketName;
        }
        log.info("上传到:{}", path);
        try {
            file = request.getPart("file");
            fileName = file.getSubmittedFileName();
            // file.write(fileName);
        } catch (Throwable e) {
            log.error("获取文件失败", e);
            return ApiResponse.builder().code(ReturnEnum.A_USER_CLIENT_ERROR.getCode()).message("fail").build();
        }
        log.info("fileName:{}", fileName);
        try {
            InputStream in = file.getInputStream();
            PutObjectOptions putObjectOptions = new PutObjectOptions(in.available(), 5242880L);
            putObjectOptions.setContentType("application/octet-stream");
            minioClient.putObject(path, fileName, in, putObjectOptions);
        } catch (Throwable e) {
            log.error("上传文件失败:{}", fileName, e);
            return ApiResponse.builder().code(ReturnEnum.A_USER_CLIENT_ERROR.getCode()).message("fail").build();
        }
        return ApiResponse.builder().code(ReturnEnum.SUCCESS.getCode()).message("ok").build();
    }
}
